package com.katze.common.http;

import com.katze.common.Code;
import com.katze.common.Delete;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.function.Function;

public final class ResponseDownloadHelper {

    private static final Logger log = LoggerFactory.getLogger(ResponseDownloadHelper.class);

    public static final String CONTENT_FILENAME = "Content-Filename";

    private final HttpServletResponse response;

    private String content;

    private byte[] buffer = new byte[1024 * 1024];

    public ResponseDownloadHelper(HttpServletResponse response) {
        this.response = response;
    }

    public ResponseDownloadHelper header(String name, String... value) {
        this.response.addHeader(name, String.join(",", value));
        return this;
    }

    public ResponseDownloadHelper content(String contentType) {
        this.content = contentType;
        return this;
    }

    public ResponseDownloadHelper buffer (byte[] buffer) {
        this.buffer = buffer;
        return this;
    }

    public Delete<Boolean> load (File source) {
        try (InputStream input = new FileInputStream(source); OutputStream output = response.getOutputStream()){
            response.setContentType(Objects.toString(content, "application/octet-stream"));
            response.setContentLengthLong(source.length());
            header("Access-Control-Expose-Headers", CONTENT_FILENAME);
            header("Content-Filename", URLEncoder.encode(source.getName(), StandardCharsets.UTF_8));
            for (int len = input.read(buffer); len != -1; len = input.read(buffer)) {
                output.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            log.error("{} 文件不存在", source.getAbsolutePath());
            response.setStatus(Code.C51001.getCode());
        } catch (Exception e) {
            response.setStatus(Code.C500.getCode());
            throw new RuntimeException(e);
        }
        return () -> source.exists() && source.delete();
    }

    public void load (Function<HttpServletResponse, InputStream> func) {
        response.setContentType(Objects.toString(content, "application/octet-stream"));
        response.setHeader("Access-Control-Expose-Headers", CONTENT_FILENAME);
        try (OutputStream output = response.getOutputStream(); InputStream input = func.apply(response)){
            for (int len = input.read(buffer); len != -1; len = input.read(buffer)) {
                output.write(buffer, 0, len);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
